puts "hello world !"

# 单行注释
=begin
asd
=end
# TODO
# FIXME
# HACK
# OPTIMIZE
# REVIEW

puts true.class
puts false.class
puts 12.class
puts nil.class
puts 180_0_0_0
puts 100 / 3
puts 100 / 3.3
puts Integer(1)

# 方法定义
def eatMethod(fruit)
  puts "I eat #{fruit}!"
end

eatMethod("Apple")

a = Rational(1, 2)
puts a.class
puts (0.1 + 0.2 == 0.3)
puts (1 + 2 == 3)

puts Float::INFINITY

require 'bigdecimal'

puts BigDecimal('1.0') + BigDecimal('2.1')

puts 1 / 2
puts 1 % 2
puts 1 / 2.0
puts 1 == 1.0 # ==用于比较值，除数字以外，其他类型可重写规则
puts 1.equal?(1.0) # equal用于比较是否是同一个对象(内存地址是同一个)
puts 1.eql?(1.0) # eql用于比较值和类型

# 奇偶性
puts 1.odd?
puts 1.even?

## 小数点位保留
puts 2.5.ceil # 返回不小于该数字的最大整数
puts 2.5.round # 返回四舍五入的整数
puts 2.5.floor # 返回不大于该数字的最大整数

puts 1.to_s == "1"
puts 2.to_f.eql?(2.0)
puts "00000"
puts "3".to_i.equal?(3)

a = "23"
b = '23'
puts a == b
b = a;
puts a.object_id == b.object_id
puts a.object_id
puts b.object_id
puts 'what\'s your name?'
puts 'aa \\'

# 字符串学习
# 单引号创建的字符串不支持转移与插值（#{}）
a = 'asda'
puts '#{a}'
puts "#{a}"

puts '1' + "22"
puts %q!字符串1!
puts %q{字符串2}
puts %q<字符串3>
puts %q[字符串4]
puts %Q{字符串5}
# Ruby on Rails  主流web开发框架
# RubyGems Ruby的包管理工具
query = <<SQL
SELECT *FROM FOOD
WHERE A=1
SQL
puts query
puts "开始学习Ruby字符串对象"

string = %Q{字符串萨达发给我}
stringEmpty = ""
string.length == string.size
puts string.empty?
puts string[0, 3]
puts string[1.6]
puts string[1.- 3]
puts string[1..-3]
puts string[1...-3]
string[0] = "我"
puts string
puts string.include? "我"
puts string.include? ""
puts stringEmpty.include? ""
puts string.index "我"
puts string.rindex "我"
puts string.rindex "我符"
puts string.start_with?
puts string.end_with?
string11 = "sdasd"
puts string11.strip # 去除空格，生成新的字符串
puts string11.strip! # 直接修改原字符串，去除空格，如果没有空格，返回nil
string.delete_prefix "我"
string.delete_suffix "我"
string.split(",")
=begin 字符串拼接的几种方式
1.使用+号，每次都生成新的字符串
2.使用<<，不生成新的字符串
3.使用concat，不生成新的字符串
4.双引号字符串使用#{}，插值，每次都生成新的字符串
5.使用*，每次都生成新的字符串
6.使用array.join
=end
string << string11
string.concat(string11)
puts (string * 3)
array = ["1", "2", "3"]
var = array.join
string.each_char { |char| puts char } # 遍历字符串并逐个打印
count = 0
string.each_char { |char| count += char.length } # 遍历字符串并逐个打印
puts count
string.chars.each { |char| puts char } # 遍历字符串并逐个打印

# 标志对象
puts :title.class

# 变量
=begin
全局变量
实例变量
类变量
局部变量
=end
name = "leizx"
@name = "leizx"
$age = 16
puts @name.class
puts $age.class

# 数组
a1 = Array.new(3)
a2 = ["1", 2, 1.2]
a3 = %w[2 3]
a3 = %w!2 3!
a4 = %i[21 撒旦 34]
p a1
p a2
p a3
p a4
# Hash
a = Hash["1" => 1, "2" => 2, "3" => 3]
b = ["1" => "2"]
c = { "1" => "2" }
puts "------------"
puts a
puts b
puts c
d = { :a => 1, :b => 2 } # 标志对象的hash写法
e = { a: 1, b: 2 } # 标志对象的hash写法
puts d, e
puts e[:a]

a = { "one" => "eins" }
b = { "two" => "zwei" }
puts a.merge(b)
puts a

# 方法
def eat()
  str = "I eat"
end

puts eat

def eat2(fruit)
  fruit
end

puts eat2("apple")

def eat3(*fruit)
  fruit.each { |fruit| puts fruit }
end

eat3("apple", "banana")

puts true if 0

# 私有方法只能在类中被调用
# protected方法只能被类或者继承类使用
class FirstClass

  def second_method
    puts "second method"
    first_method
  end

  protected

  def third_method
    puts "third method"
    first_method
  end

  private

  def first_method
    puts "first method"
  end
end

var = FirstClass.new
var.second_method

# Ruby中的类是开放的
# method?返回值一般是boolean
# method！方法一般代表会更改原对象
# 单例方法 只针对某个类的实例的方法
class Singleton
  def m1
    puts "m1"
  end
end

obj = Singleton.new
obj2 = Singleton.new
puts obj.m1

def obj.m1 # 创建单例方法
  puts "obj.m1"
end

puts obj.m1
puts obj2.m1

# 消息传递，非函数调用
# 这个
1 + 2
# 跟下面一样
1.+ 2
# 跟下面一样
1.send "+", 2

# 代码块也是对象
def m1(&block)
  block
end

obj = m1 { |a, b| a + b }
puts obj.class

# 类
puts "判断某个对象是否是某个类的实例:" << ("aa".is_a? (String)).to_s
puts "判断某个对象是否是某个类的实例:".concat (11.is_a? (Integer)).to_s

class People
  attr_reader :name
  attr_writer :name

  def initialize(name, age)
    @name = name
    @age = age
  end

  def say_hello
    puts "Helllo everyone！,my name is #{@name},".concat "my age is #{@age}!"
  end

  def say_to_other(other)
    name = other.name
    puts "hello,#{name},my name is #{self.name}"
  end
end

p = People.new("leizx", 23)
p.say_to_other(People.new("jianghong", 25))
p.name = "leizx1"
puts p.name

# 模块的定义
module FirstModule
  # 类方法 通过FirstModule.eat()调用
  def self.eat(fruit)
    fruit + "1"
  end

  # 实例方法 需要类include后来调用
  def eat(fruit)
    fruit + "2"
  end
end
puts FirstModule.class.equal? Module # module属于Module类
class FirstModuleClass
  include FirstModule
end

puts FirstModule.eat("apple")
puts FirstModuleClass.new.eat("apple")

## 条件控制语句
if 1 < 2
  puts "1"
elsif 2 < 3
  puts "2"
else
  puts "3"
end

puts "1" if 1 < 2

if not 2 < 1
  puts "2"
end

case "122"
when "1" then 1

else puts "1"
end

# 范围 Range
puts (1..10).include? 10 # ..包含最后一个
puts (1...10).include? 10 # ...不包含最后一个
(1..10).end
puts (1..10).to_a
range = 1..10
range.class
range.each { |a| puts a }

# 循环 while
i = 0
while i < 5
  puts i
  i += 1
end
# 循环 until
j = 0
until j == 5
  puts j
  j += 1;
end
# 循环 for in [范围/数组/哈希]
for i in (1..10)
  puts i
end

array = [1, 2, 3]
for a in array
  puts a
end

hash = { "a": 1, "b": 2 }
for key, value in hash
  puts value
end

# 迭代器
array = [1, 2, 3]
# each
array.each { |a| puts a }
{ a: 1, b: 2, c: 3 }.each do |key, value|
  puts key, key.class
  puts value, value.class
end
# each_with_index
array.each_with_index do |a, i|
  print a, i
end
# map/collect
array.map { |a| puts (a * a) }

# inject  累加
puts "inject"
puts array.to_s
var = array.inject { |sum, a| sum += a }
puts var

# select 类似过滤
var = array.select { |a| a % 2 == 0 }
puts var

# find 类似过滤(取第一个)
var = array.find { |a| a > 1 }
puts var

# ruby的块
# do ** end (多行)
# {}   (单行)
5.times do
  puts "hi"
end
5.times { puts "hi" }
# 隐式创建一个带有块的方法,使用yield标识块将在此处被调用
def my_method
  yield if block_given?
end

my_method { puts "first block method created" }

# 显示创建一个带有块的方法
def second_block_method name, age, &block
  puts name
  block.call if block
end

second_block_method("leizx", "adsa") { puts ",你好" }

# 显示创建一个带有块的方法并传递参数
def third_block_method name, age, &block
  block.call("jianghong") if block
end

third_block_method("leizx", "adsa") { |a| puts ",你好" << a }

# IO
$stdout.puts "Hello world" # 输出
# puts 1.to_s=p 1
p 1

=begin
input = $stdin.gets  #输入
p input
p gets
=end

# 读文件
=begin
var = IO.sysopen("C:\\Users\\leizx\\Desktop\\1.txt")
a = IO.new(var)
p a.gets
p a.gets
=end
# 写文件
File.open 'C:/Users/leizx/Desktop/1.txt', 'a' do |file|
  file.puts "我是被写进来的"
end

# 异常
def raise_method(x)
  raise ArgumentError, 'Argument is not Numeric' unless x.is_a? Numeric # 抛出异常
  puts x / 2
end

raise_method(1)
# raise_method("22")

# 异常处理 rescue
a = "22"
begin
  puts raise_method a
rescue SecurityError => e1
rescue ArgumentError => e2
  puts "异常被捕获"
  a = 2
  retry
end

# 时间类
time = Time.now
puts Time.new
b = Time.new(2024, 12, 19, 16, 17, 59, "+0800")
puts b.to_i
puts Time.at 1456464
time.year
time.month
time.zone
time.friday?

# 时间格式化
var = time.strftime("%m/%d/%Y")
puts var
puts b.to_i # 根据Time获取时间戳
puts b > b + 10 # 直接做比较即可，+ - 以秒为单位
puts Time.now + 24 * 60 * 60 # 获取明天的时间

# date  需要引包
require 'date'
Date.today
var = Date.new 2024, 12, 19
puts var
puts Date.parse('2024-12-19')

# date转字符串
puts Date.new(2024, 12, 27).strftime("%m/%d/%Y")
# time 转字符串
puts Time.now.strftime("%Y-%m-%d %H:%M:%S")
# date 转 time
puts Date.today.to_time
# time转date
puts Time.now.to_date
# 字符串转date
puts Date.parse('2024-12-27')
# 字符串转time
require 'time'
puts Time.parse '2024-12-27 12:00:00'
puts Time.strptime '2024-12-27 12:00:00', '%Y-%m-%d %H:%M:%S'

Date::MONTHNAMES.each { |m| puts m }

# Math类
puts Math.sqrt 16
p Math.constants

# Dir类
puts Dir.pwd
puts Dir.entries('.')
Dir.foreach('.') { |f| puts f }

# File 类
file = File.new("12.txt", "w+")
p file.closed?
file.write("12.txt")

file = File.new("13.txt", "w+")
file.puts("111111111111111111")
file.putc "1"
file.puts("222222222222222222")
file.rewind # 将指针移动到开头
p file.getc.chr
p file.readline
p file.readline

# 元编程:v1
class CarModel
  ATTRS = ["age", "name"]

  ## 动态定义方法，attr为方法的前缀，methodParam代表该方法的形参，instance_variable_set代表setter方法(针对成员变量age_info,name_info)
  ATTRS.each do |attr|
    define_method("#{attr}_info=") do |methodParam|
      instance_variable_set("@#{attr}_info", methodParam)
    end
  end
end

# 元编程:v2
class CarModel
  attr_accessor :age, :name
end

# 元编程：v3
=begin
class CarModel
  Array :name, :age

  def self.attr_method(*args)
    args.each do |arg|
      attr_accessor "#{arg}_info", "#{arg}_price"
    end
  end
end
=end
# 动态定义方法
class Account
  attr_accessor :count
  # 动态定义自增1的方法
  (1..99).each do |i|
    define_method ("credit_#{i}".to_sym) do
      self.count = count + i
    end
  end

  # 动态定义自减1的方法
  (1..99).each do |i|
    define_method ("debit_#{i}".to_sym) do
      self.count = count - i
    end
  end

  def method_1(name)
    p name
  end

  def method_block(&block)
    block.call if block
  end

  def initialize (count)
    @count = count
  end
end

obj = Account.new(20)
obj.credit_31
puts obj.count
obj.debit_32
puts obj.count
# 使用send来动态调用方法
obj.send(:credit_32)
p obj.count
obj.send(:method_1, "leizx")
obj.send(:method_block) { p "my name is" }  # block调用

class Person
  attr_accessor :name,:age

  def initialize(name,age)
    @name = name
    @age = age
  end
end
class  Student < Person

end
# 类的本质
p Student.superclass
p Student.superclass.superclass

obj1 = Student.new("leizx",1)
p obj1.class
p Student.class   #所有类都是Class的实例
p Class.class
p Class.superclass  #Module
p Class.superclass.superclass
p Class.superclass.superclass.superclass

#继承关系，自下往上找
p obj1.name,obj1.age
p Student.ancestors


# Ruby的eval使用方式 eval
puts eval("1+1")
# eval  执行参数为Ruby代码
eval <<-DEFINE_CLASS
class Person
attr_accessor :name
def initialize(name)
@name = name
end 
end
DEFINE_CLASS
var = Person.new("leizx")
puts var.name


# instance_eval
class A
  attr_accessor :name
  def initialize(name)
    @name = name
  end
end


a = A.new("A")
b = A.new("B")
a.instance_eval do
  def m1
    "m1"
  end
end
a.m1
# b.m1   # 抛出异常，没有为b对象定义方法

A.instance_eval do
  def m2
    "m2"
  end
end
puts A.m2
# class_eval  给类定义方法
class B
end
B.class_eval do
  def m3
    "m3"
  end
end
puts B.new.m3


# 动态处理各种类型变量
# 处理局部变量
b = binding # bingdig代表上下文环境，包括变量，方法，self等信息，可以在代码运行时动态访问和修理这些信息
(1..2).each do |num|
  b.local_variable_set("a_#{num}".to_sym, num)
end

(1..2).each do |num|
  puts b.local_variable_get("a_#{num}".to_sym)
end


# 动态处理实例变量
class ABC
  def initialize
    (1..3).each do |num|
      # 类被实例化时，动态创建3个实例变量
      instance_variable_set("@a_#{num}".to_sym,num)
    end
  end

  (1..3).each do |num|
    # 动态定义方法，内容为获取对应字段的值
    define_method("a_#{num}".to_sym) do
      instance_variable_get("@a_#{num}".to_sym)
    end
  end
end

var = ABC.new
puts var.a_1
puts var.a_2
puts var.a_3

# 动态处理类变量